package br.org.bertol.mestrado;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;

import br.org.bertol.mestrado.engine.Objective;

/**
 * @author contaqualquer
 */
public class Verify<T> {

    /**
     * Conjunto de restrições fortes.
     */
    private transient List<List<Integer>> strongConstraint;

    /**
     * Conjunto de classes.
     */
    private transient ArrayList<T>        classes;

    /***/
    private transient boolean             systemEnable = false;

    /***/
    private final transient String        system;

    /***/
    private final transient String        sourc;

    /**
     * Lista de Objetivos.
     */
    private final transient Objective[]   objectives;

    public Verify(final Objective[] objectives, final String source,
        final String sistema) {

        strongConstraint = new ArrayList<List<Integer>>();

        classes = new ArrayList<T>();

        this.objectives = objectives;

        system = sistema;

        sourc = source;

        try {

            uploadSystem(sistema);

            // instancia classes
            discoverOperador(objectives[0].getParameters());

        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
    }

    private void uploadSystem(final String... sistemas)
            throws IOException {
        systemEnable = true;

        for (String sistema : sistemas) {
            for (Objective objective : objectives) {

                objective.loadParameters(sourc, sistema);

                if (objective.getParameters().size() == 0) {
                    Logger.getLogger(this.getClass())
                            .error(
                                   "Sistema " + sistema
                            + " deve ter a matrix de "
                            + objectives.toString()
                            + " definida.");
                    systemEnable = false;
                    break;
                }

            }
        }
        // }
    }

    /**
     * Monta uma lista com todas as classes dos sistema e as classes iniciais.
     * @param numClasses
     *            Total de classes do sistema
     * @return Array com todas as classes disponíveis
     */
    private ArrayList<T> discoverClasses(final int numClasses) {
        /*
         * // instancias as classes do problema for (int i = 0; i < numClasses;
         * i++) { classes.add(i + 1); }
         */

        return classes;
    }

    /**
     * Monta uma lista com todas as classes dos sistema e as classes iniciais.
     * @param numClasses
     *            Total de classes do sistema
     * @return Array com todas as classes disponíveis
     */
    @SuppressWarnings("unchecked")
    private ArrayList<T> discoverOperador(final List<List<Object>> list2) {

        // instancias as classes do problema
        for (List<Object> list : list2) {
            for (Object t : list) {
                classes.add((T) t);

            }
        }

        return classes;
    }

    /**
     * @return {@link List} Retorna todas as classes possiveis de começar um
     *         caminho.
     */
    public final List<Integer> getStartClasses() {

        final ArrayList<Integer> startClasses = new ArrayList<Integer>();
        /*
         * for (Integer classe : classes) {
         * 
         * if (strongConstraint.get(classe - 1).size() == 1) {
         * startClasses.add(classe.intValue()); } }
         */
        return startClasses;
    }

    /**
     * @return the classes
     */
    @SuppressWarnings("unchecked")
    public final List<T> getClasses() {
        return (ArrayList<T>) classes.clone();
    }

    /**
     * @return the height
     */
    public final Objective[] getObjectives() {
        return objectives;
    }

    /**
     * @return the systemEnable
     */
    public final boolean isSystemEnable() {
        return systemEnable;
    }

    /**
     * @return the strongConstraint
     */
    public final List<List<Integer>> getStrongConstraint() {

        try {

            strongConstraint = Objective.loadStrongConstraint(sourc, system);

        } catch (IOException e) {
            Logger
                    .getLogger(this.getClass())
                    .error(
                           "Sistema "
                    + system
                    + " deve ter a matrix de precedência definida.", e);
            System.exit(1);
        }

        return strongConstraint;
    }
}
